package com.woniuxy.yoga.user.web.controller;


import cn.hutool.core.bean.BeanUtil;
import com.woniuxy.yoga.commons.core.model.PageInfo;
import com.woniuxy.yoga.commons.core.model.Result;
import com.woniuxy.yoga.commons.core.util.FileUtil;
import com.woniuxy.yoga.commons.core.util.JWTUtil;
import com.woniuxy.yoga.commons.redis.util.RedisUtil;
import com.woniuxy.yoga.commons.web.log.YogaLog;
import com.woniuxy.yoga.commons.web.util.WebUtil;
import com.woniuxy.yoga.user.dao.model.UserInfo;
import com.woniuxy.yoga.user.model.dto.FollowCoachRankDto;
import com.woniuxy.yoga.user.model.dto.FollowStoreRankDto;
import com.woniuxy.yoga.user.model.dto.UserInfoDto;
import com.woniuxy.yoga.user.model.dto.UserInfoToken;
import com.woniuxy.yoga.user.model.exception.UserException;
import com.woniuxy.yoga.user.model.exception.UserExceptionCode;
import com.woniuxy.yoga.user.model.form.*;
import com.woniuxy.yoga.user.model.param.*;
import com.woniuxy.yoga.user.permission.Permission;
import com.woniuxy.yoga.user.service.UserInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * <p>
 * 用户信息表 前端控制器
 * </p>
 *
 * @author 韦用文,刘存益,郎腾霄
 * @since 2023年11月28日
 */
@RestController
@RequestMapping("/userInfo")
@Api(tags = "用户服务管理")
@Validated
public class UserInfoController {

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private RedisUtil redisUtil;


    /**
     * 发送用户注册验证码
     * @param form form
     * @return Result<String>
     */
    @PostMapping("/sendUserRegCode.us")
    @ApiOperation("发送用户注册验证码")
    @YogaLog("发送用户注册验证码")
    public Result<String> sendUserRegCode(@Valid @RequestBody SendUserRegCodeForm form){
        userInfoService.sendUserRegCode(BeanUtil.toBean(form, SendUserRegCodeParam.class));
        return Result.getResult(String.class).setMessage("发送注册短信成功");
    }

    /**
     * 用户注册
     * @param form form
     * @return String
     * @throws Exception Exception
     */
    @PostMapping("/userRegister.us")
    @ApiOperation("用户注册")
    @YogaLog("用户注册")
    public Result<String> userRegister(@Valid @RequestBody UserRegisterForm form) throws Exception {
        userInfoService.userRegister(BeanUtil.toBean(form, UserRegisterParam.class));
        return Result.getResult(String.class).setMessage("注册成功");
    }

    /**
     * 发送用户登录验证码
     * @param form form
     * @return String
     */
    @PostMapping("/sendUserLogCode.us")
    @ApiOperation("发送用户登录验证码")
    @YogaLog("发送用户登录验证码")
    public Result<String> sendUserLogCode(@Valid @RequestBody SendUserLogCodeForm form){
        userInfoService.sendUserLogCode(BeanUtil.toBean(form, SendUserLogCodeParam.class));
        return Result.getResult(String.class).setMessage("发送成功");
    }

    /**
     * 用户验证码登录
     * @param form form
     * @return UserInfoDto
     */
    @PostMapping("/loginByCode.us")
    @ApiOperation("验证码登录")
    @YogaLog("用户验证码登录")
    public Result<UserInfoDto> loginByCode(@Valid @RequestBody LoginByCodeForm form){
        //获取登录ip地址
        String ip = WebUtil.getRequest().getRemoteAddr();
        LoginByCodeParam param = BeanUtil.toBean(form, LoginByCodeParam.class);
        param.setIp(ip);
        UserInfoDto userInfoDto = userInfoService.loginByCode(param);
        //生成token
        Map<String, Object> map = BeanUtil.beanToMap(BeanUtil.toBean(userInfoDto, UserInfoToken.class));
        String accessToken = JWTUtil.createUserToken(map, 30);
        String refreshToken = JWTUtil.createUserToken(map, 3 * 60 * 24);
        //存入长token
        redisUtil.set(accessToken,refreshToken,24 * 60 * 60 * 7L);
        //响应短token
        WebUtil.getResponse().setHeader("authen_token",accessToken);
        WebUtil.getResponse().setHeader("Access-Control-Expose-Headers","authen_token");
        return Result.getResult(UserInfoDto.class).setMessage("登录成功").setData(userInfoDto);
    }

    /**
     * 用户密码登录
     * @param form form
     * @return UserInfoDto
     */
    @PostMapping("/loginByPass.us")
    @ApiOperation("密码登录")
    @YogaLog("用户密码登录")
    public Result<UserInfoDto> loginByPass(@Valid @RequestBody LoginByPassForm form){
        //获取登录ip地址
        String ip = WebUtil.getRequest().getRemoteAddr();
        LoginByPassParam param = BeanUtil.toBean(form, LoginByPassParam.class);
        param.setIp(ip);
        UserInfoDto userInfoDto = userInfoService.loginByPass(param);
        //生成token
        Map<String, Object> map = BeanUtil.beanToMap(BeanUtil.toBean(userInfoDto, UserInfoToken.class));
        String accessToken = JWTUtil.createUserToken(map, 30);
        String refreshToken = JWTUtil.createUserToken(map, 3 * 60 * 24);
        //存入长token
        redisUtil.set(accessToken,refreshToken,24 * 60 * 60 * 7L);
        //响应短token
        WebUtil.getResponse().setHeader("authen_token",accessToken);
        WebUtil.getResponse().setHeader("Access-Control-Expose-Headers","authen_token");
        return Result.getResult(UserInfoDto.class).setMessage("登录成功").setData(userInfoDto);
    }

    /**
     * 禁用用户账号
     * @param form form
     * @return String
     */
    @PostMapping("/disableUser.api")
    @ApiOperation("禁用用户账号")
    @YogaLog("禁用用户账号")
    @Permission(resources = {"/user/userInfo/disableUser.api"})
    public Result<String> disableUser(@Valid @RequestBody ChangeUserStateForm form){
        userInfoService.disableUser(BeanUtil.toBean(form,ChangeUserStateParam.class));
        return Result.getResult(String.class).setMessage("禁用成功");
    }

    /**
     * 启用用户账号
     * @param form form
     * @return String
     */
    @PostMapping("/enableUser.api")
    @ApiOperation("禁用用户账号")
    @YogaLog("禁用用户账号")
    @Permission(resources = {"/user/userInfo/enableUser.api"})
    public Result<String> enableUser(@Valid @RequestBody ChangeUserStateForm form){
        userInfoService.enableUser(BeanUtil.toBean(form,ChangeUserStateParam.class));
        return Result.getResult(String.class).setMessage("启用成功");
    }

    /**
     * 删除用户账户
     * @param form form
     * @return String
     */
    @PostMapping("/delUser.api")
    @ApiOperation("删除用户账户")
    @YogaLog("删除用户账户")
    @Permission(resources = {"/user/userInfo/delUser.api"})
    public Result<String> delUser(@Valid @RequestBody ChangeUserStateForm form){
        userInfoService.delUser(BeanUtil.toBean(form,ChangeUserStateParam.class));
        return Result.getResult(String.class).setMessage("删除成功");
    }

    /**
     * 用户头像修改
     * @param image image
     * @param authen_token token
     * @return String
     * @throws IOException IOException
     */
    @PostMapping("/uploadUserAvatar")
    @ApiOperation("用户头像修改")
    @ApiImplicitParam(name = "image",value = "图片信息")
    public Result<String> uploadUserAvatar(MultipartFile image,@RequestHeader("authen_token") String authen_token) throws IOException {
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        //1取出image中的文件内容
        InputStream inputStream = image.getInputStream();
        byte[] header = new byte[8];
        inputStream.read(header,0,8);
        //2判断文件类型是否为图片
        if (!(FileUtil.isJpg(header)||FileUtil.isPng(header))){
            throw new UserException(UserExceptionCode.USER_EXCEPTION_CODE_FILE_FORMAT);
        }
        //3.生成新的图片名称
        String prefix = UUID.randomUUID().toString().replaceAll("-","");
        String fileName = prefix+"."+(FileUtil.isJpg(header)?"jpg":"png");
        //4.调用api上传
        UpdateUserAvatarParam param = new UpdateUserAvatarParam();
        param.setUserId(userId);
        param.setImage(image);
        param.setFileName(fileName);
        String path = userInfoService.updateUserAvatar(param);
        return Result.getResult(String.class).setMessage("头像修改成功").setData(path);
    }

    /**
     * 用户查询本人信息
     * @param authen_token token
     * @return UserInfoDto
     */
    @PostMapping("/findMy.us")
    @ApiOperation("用户查询本人信息")
    @YogaLog("用户查询本人信息")
    public Result<UserInfoDto> findMy(@RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        UserInfo userInfo = userInfoService.getById(userId);
        UserInfoDto userInfoDto = BeanUtil.toBean(userInfo, UserInfoDto.class);
        return Result.getResult(UserInfoDto.class).setMessage("查询成功").setData(userInfoDto);
    }

    /**
     * 分页查询用户信息
     * @return PageInfo
     */
    @PostMapping("/findUsers.api")
    @ApiOperation("分页查询用户信息")
    @YogaLog("分页查询用户信息")
    @Permission(resources = {"/user/userInfo/findUsers.api"})
    public Result<PageInfo> findUsers(@Valid @RequestBody ListUsersForm form){
        PageInfo pageInfo = userInfoService.findUsers(BeanUtil.toBean(form,ListUsersParam.class));
        return Result.getResult(PageInfo.class).setMessage("查询成功").setData(pageInfo);
    }

    /**
     * 修改用户基本信息
     * @param form form
     * @param authen_token token
     * @return String
     */
    @PostMapping("/updateUserInfo.us")
    @ApiOperation("修改用户基本信息")
    @YogaLog("修改用户基本信息")
    public Result<String> updateUserInfo(@Valid @RequestBody UpdateUserInfoForm form,@RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        UpdateUserInfoParam param = BeanUtil.toBean(form, UpdateUserInfoParam.class);
        param.setUserId(userId);
        userInfoService.updateUserInfo(param);
        return Result.getResult(String.class).setMessage("修改信息成功");
    }

    /**
     * 修改密码
     * @param form form
     * @return String
     */
    @PostMapping("/changePwd.us")
    @ApiOperation("修改密码")
    @YogaLog("修改密码")
    public Result<String> changePwd(@Valid @RequestBody ChangePwdForm form,@RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        ChangePwdParam param = BeanUtil.toBean(form, ChangePwdParam.class);
        param.setUserId(userId);
        userInfoService.changePwd(param);
        return Result.getResult(String.class).setMessage("修改密码成功");
    }

    /**
     * 实名认证
     * @return String
     */
    @PostMapping("/identify.us")
    @ApiOperation("实名认证")
    @YogaLog("实名认证")
    public Result<String> identify(@Valid @RequestBody IdentifyForm form,@RequestHeader("authen_token") String authen_token) throws Exception {
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        IdentifyParam param = BeanUtil.toBean(form, IdentifyParam.class);
        param.setUserId(userId);
        userInfoService.identify(param);
        return Result.getResult(String.class).setMessage("认证成功");
    }

    /**
     * 发送用户修改手机验证码
     * @param form form
     * @return String
     */
    @PostMapping("/sendChangePhoneCode.us")
    @ApiOperation("发送用户修改手机验证码")
    @YogaLog("发送用户修改手机验证码")
    public Result<String> sendChangePhoneCode(@Valid @RequestBody SendUserChangePhoneCodeForm form){
        userInfoService.sendChangePhoneCode(BeanUtil.toBean(form, SendUserChangePhoneCodeParam.class));
        return Result.getResult(String.class).setMessage("发送短信成功");
    }

    /**
     * 用户更换手机号
     * @return String
     */
    @PostMapping("/changePhone.us")
    @ApiOperation("用户更换手机号")
    @YogaLog("用户更换手机号")
    public Result<String> changePhone(@Valid @RequestBody ChangePhoneForm form,@RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        ChangePhoneParam param = BeanUtil.toBean(form, ChangePhoneParam.class);
        param.setUserId(userId);
        userInfoService.changePhone(param);
        return Result.getResult(String.class).setMessage("修改成功");
    }

    /**
     * 根据id查询用户信息
     * @param userId 用户id
     * @return 用户信息对象
     */
    @GetMapping("/getByUserId/{userId}")
    @ApiOperation("根据id查询用户")
    public Result<UserInfoDto> getByUserId(@PathVariable("userId") Integer userId){
        UserInfo userInfo = userInfoService.getById(userId);
        UserInfoDto userInfoDto = BeanUtil.toBean(userInfo, UserInfoDto.class);
        return Result.getResult(UserInfoDto.class).setMessage("查询成功").setData(userInfoDto);
    }

    /**
     * 用户关注教练
     * @param coachId 教练ID
     * @param authen_token 用户ID
     * @return String
     */
    @GetMapping("/followCoach.us")
    @ApiOperation("用户关注教练")
    @YogaLog("用户关注教练")
    public Result<String> followCoach(Integer coachId,@RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        userInfoService.followCoach(userId,coachId);
        return Result.getResult(String.class).setMessage("关注教练成功");
    }

    /**
     * 用户取消关注教练
     * @param coachId 教练id
     * @param authen_token token
     * @return String
     */
    @GetMapping("/cancelFollowCoach.us")
    @ApiOperation("用户取消关注教练")
    public Result<String> cancelFollowCoach(Integer coachId,@RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        userInfoService.cancelFollowCoach(userId,coachId);
        return Result.getResult(String.class).setMessage("取消关注成功");
    }

    /**
     * 分页查询关注教练列表
     * @param pageNum 当前页数
     * @param pageSize 每页条数
     * @param authen_token token
     * @return PageInfo
     */
    @GetMapping("/searchFollowCoachRank.us")
    @ApiOperation("分页查询关注教练列表")
    @YogaLog("分页查询关注教练列表")
    public Result<PageInfo> searchFollowCoachRank(Integer pageNum,Integer pageSize, @RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        PageInfo pageInfo = userInfoService.searchFollowCoachRank(pageNum,pageSize,userId);
        return Result.getResult(PageInfo.class).setMessage("查询成功").setData(pageInfo);
    }

    /**
     * 查询关注教练排行榜
     * @return List<FollowCoachRankDto>
     */
    @GetMapping("/searchFollowCoachRankList")
    @ApiOperation("查询关注教练排行榜")
    @YogaLog("查询关注教练排行榜")
    public Result<List<FollowCoachRankDto>> searchFollowCoachRankList(){
        List<FollowCoachRankDto> followCoachRankDtos = userInfoService.searchFollowCoachRankList();
        return Result.getListResult(FollowCoachRankDto.class).setMessage("查询关注排行榜成功").setData(followCoachRankDtos);
    }

    /**
     * 教练分页查看被关注的用户信息
     * @param form 查询参数
     * @param authen_token token
     * @return PageInfo
     */
    @PostMapping("/listCoachFollowedUsers.co")
    @ApiOperation("教练分页查看被关注的用户信息")
    @YogaLog("教练分页查看被关注的用户信息")
    public Result<PageInfo> listCoachFollowedUsers(ListFollowedUsersForm form,@RequestHeader("authen_token") String authen_token){
        Integer coachId = JWTUtil.getCoachId(redisUtil.get(authen_token));
        ListFollowedUsersParam param = BeanUtil.toBean(form, ListFollowedUsersParam.class);
        param.setId(coachId);
        PageInfo pageInfo = userInfoService.listCoachFollowedUsers(param);
        return Result.getResult(PageInfo.class).setMessage("查询成功").setData(pageInfo);
    }

    /**
     * 用户关注场馆
     * @param storeId 场馆id
     * @param authen_token token
     * @return String
     */
    @GetMapping("/followStore.us")
    @ApiOperation("用户关注场馆")
    @YogaLog("用户关注场馆")
    public Result<String> followStore(Integer storeId,@RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        userInfoService.followStore(userId,storeId);
        return Result.getResult(String.class).setMessage("关注场馆成功");
    }

    /**
     * 用户取消关注场馆
     * @param storeId 场馆id
     * @param authen_token token
     * @return String
     */
    @GetMapping("/cancelFollowStore.us")
    @ApiOperation("用户取消关注场馆")
    @YogaLog("用户取消关注场馆")
    public Result<String> cancelFollowStore(Integer storeId,@RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        userInfoService.cancelFollowStore(userId,storeId);
        return Result.getResult(String.class).setMessage("取消关注场馆成功");
    }

    /**
     * 分页查询关注场馆列表
     * @param pageNum 当前页数
     * @param pageSize 每页条数
     * @param authen_token token
     * @return PageInfo
     */
    @GetMapping("/searchFollowStoreRank.us")
    @ApiOperation("分页查询关注场馆列表")
    @YogaLog("分页查询关注场馆列表")
    public Result<PageInfo> searchFollowStoreRank(Integer pageNum,Integer pageSize, @RequestHeader("authen_token") String authen_token){
        Integer userId = JWTUtil.getUserId(redisUtil.get(authen_token));
        PageInfo pageInfo = userInfoService.searchFollowStoreRank(pageNum,pageSize,userId);
        return Result.getResult(PageInfo.class).setMessage("查询成功").setData(pageInfo);
    }

    /**
     * 查询关注场馆排行榜
     * @return List<FollowStoreRankDto>
     */
    @GetMapping("/searchFollowStoreRankList")
    @ApiOperation("查询关注场馆排行榜")
    @YogaLog("查询关注场馆排行榜")
    public Result<List<FollowStoreRankDto>> searchFollowStoreRankList(){
        List<FollowStoreRankDto> followStoreRankDtos = userInfoService.searchFollowStoreRankList();
        return Result.getListResult(FollowStoreRankDto.class).setMessage("查询场馆关注排行榜成功").setData(followStoreRankDtos);
    }

    /**
     * 场馆分页查看被关注的用户信息
     * @param form 查询参数
     * @param authen_token token
     * @return PageInfo
     */
    @PostMapping("/listStoreFollowedUsers.bu")
    @ApiOperation("场馆分页查看被关注的用户信息")
    @YogaLog("场馆分页查看被关注的用户信息")
    public Result<PageInfo> listStoreFollowedUsers(ListFollowedUsersForm form,@RequestHeader("authen_token") String authen_token){
        Integer businessId = JWTUtil.getBusinessId(redisUtil.get(authen_token));
        ListFollowedUsersParam param = BeanUtil.toBean(form, ListFollowedUsersParam.class);
        param.setId(businessId);
        PageInfo pageInfo = userInfoService.listStoreFollowedUsers(param);
        return Result.getResult(PageInfo.class).setMessage("查询成功").setData(pageInfo);
    }

    /**
     * 用户注销账号
     * @param authen_token 令牌
     * @return String
     */
    @PostMapping("/userDelete.us")
    @ApiOperation("用户注销账号")
    @YogaLog("用户注销账号")
    public Result<String> userDelete(@RequestHeader String authen_token){
        Integer userId = JWTUtil.getUserId(authen_token);
        userInfoService.userDelete(userId);
        //注销成功后退出账号
        redisUtil.delete(authen_token);
        return Result.getResult(String.class).setMessage("注销账号成功");
    }

    /**
     * 通过用户id集合查询用户信息
     * @param form 参数
     * @return pageinfo
     */
    @PostMapping("selectUsersByIds")
    @ApiOperation("通过用户id集合查询用户信息")
    @YogaLog("通过用户id集合查询用户信息")
    public Result<PageInfo> selectUsersByIds(@RequestBody @Valid SelectUsersByIdsForm form){
        PageInfo pageInfo = userInfoService.selectUsersByIds(BeanUtil.toBean(form,SelectUsersByIdsParam.class));
        return Result.getResult(PageInfo.class).setMessage("查询成功").setData(pageInfo);
    }
}

